package com.ellen.mac.chatdemo.fragment;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;

import com.avos.avoscloud.AVException;
import com.avos.avoscloud.AVFile;
import com.avos.avoscloud.im.v2.AVIMConversation;
import com.avos.avoscloud.im.v2.AVIMException;
import com.avos.avoscloud.im.v2.AVIMMessage;
import com.avos.avoscloud.im.v2.AVIMMessageOption;
import com.avos.avoscloud.im.v2.callback.AVIMConversationCallback;
import com.avos.avoscloud.im.v2.callback.AVIMMessageRecalledCallback;
import com.avos.avoscloud.im.v2.callback.AVIMMessageUpdatedCallback;
import com.avos.avoscloud.im.v2.callback.AVIMMessagesQueryCallback;
import com.avos.avoscloud.im.v2.messages.AVIMAudioMessage;
import com.avos.avoscloud.im.v2.messages.AVIMImageMessage;
import com.avos.avoscloud.im.v2.messages.AVIMRecalledMessage;
import com.avos.avoscloud.im.v2.messages.AVIMTextMessage;
import com.ellen.mac.chatdemo.R;
import com.ellen.mac.chatdemo.adpter.ChatAdapter;
import com.ellen.mac.chatdemo.event.InputBottomBarEvent;
import com.ellen.mac.chatdemo.event.InputBottomBarRecordEvent;
import com.ellen.mac.chatdemo.event.TypeMessageEvent;
import com.ellen.mac.chatdemo.event.ConversationReadStatusEvent;
import com.ellen.mac.chatdemo.event.InputBottomBarTextEvent;
import com.ellen.mac.chatdemo.event.MessageResendEvent;
import com.ellen.mac.chatdemo.event.MessageUpdateEvent;
import com.ellen.mac.chatdemo.event.MessageUpdatedEvent;
import com.ellen.mac.chatdemo.utils.ChatKit;
import com.ellen.mac.chatdemo.utils.LogUtils;
import com.ellen.mac.chatdemo.utils.NotificationUtils;
import com.ellen.mac.chatdemo.view.InputBottomBar;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.io.IOException;
import java.util.List;


/**
 * 将聊天相关的封装到此 Fragment 里边，只需要通过 setConversation 传入 Conversation 即可
 */
public class ConversationFragment extends Fragment {


    protected AVIMConversation imConversation;
    private static final int REQUEST_IMAGE_PICK = 2;

    /**
     * recyclerView 对应的 Adapter
     */
    protected ChatAdapter itemAdapter;

    protected RecyclerView recyclerView;
    protected LinearLayoutManager layoutManager;

    /**
     * 负责下拉刷新的 SwipeRefreshLayout
     */
    protected SwipeRefreshLayout refreshLayout;

    /**
     * 底部的输入栏
     */
    protected InputBottomBar inputBottomBar;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.chat_room_act, container, false);
        recyclerView = view.findViewById(R.id.fragment_chat_rv_chat);
        refreshLayout = view.findViewById(R.id.fragment_chat_srl_pullrefresh);
        refreshLayout.setEnabled(false);
        inputBottomBar = view.findViewById(R.id.fragment_chat_inputbottombar);
        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
        itemAdapter = getAdpter();
        itemAdapter.resetRecycledViewPoolSize(recyclerView);
        recyclerView.setAdapter(itemAdapter);
        EventBus.getDefault().register(this);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                AVIMMessage message = itemAdapter.getFirstMessage();
                if (null == message) {
                    refreshLayout.setRefreshing(false);
                } else {
                    imConversation.queryMessages(message.getMessageId(), message.getTimestamp(), 20, new AVIMMessagesQueryCallback() {
                        @Override
                        public void done(List<AVIMMessage> list, AVIMException e) {
                            refreshLayout.setRefreshing(false);
                            if (filterException(e)) {
                                if (null != list && list.size() > 0) {
                                    itemAdapter.addMessageList(list);
                                    itemAdapter.setDeliveredAndReadMark(imConversation.getLastDeliveredAt(), imConversation.getLastReadAt());
                                    itemAdapter.notifyDataSetChanged();
                                    layoutManager.scrollToPositionWithOffset(list.size() - 1, 0);
                                }
                            }
                        }
                    });
                }
            }
        });
    }

    protected ChatAdapter getAdpter() {
        return new ChatAdapter();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (null != imConversation) {
            NotificationUtils.addTag(imConversation.getConversationId());
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (null != imConversation) {
            NotificationUtils.removeTag(imConversation.getConversationId());
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        EventBus.getDefault().unregister(this);
    }

    public void setConversation(final AVIMConversation conversation) {
        imConversation = conversation;
        refreshLayout.setEnabled(true);
        inputBottomBar.setTag(imConversation.getConversationId());
        fetchMessages();
        NotificationUtils.addTag(conversation.getConversationId());
        if (!conversation.isTransient()) {
            if (conversation.getMembers().size() == 0) {
                conversation.fetchInfoInBackground(new AVIMConversationCallback() {
                    @Override
                    public void done(AVIMException e) {
                        if (null != e) {
                            LogUtils.logException(e);
                        }
                        itemAdapter.showUserName(conversation.getMembers().size() > 2);
                    }
                });
            } else {
                itemAdapter.showUserName(conversation.getMembers().size() > 2);
            }
        } else {
            itemAdapter.showUserName(true);
        }
    }

    /**
     * 拉取消息，必须加入 conversation 后才能拉取消息
     */
    private void fetchMessages() {
        imConversation.queryMessages(new AVIMMessagesQueryCallback() {
            @Override
            public void done(List<AVIMMessage> messageList, AVIMException e) {
                if (filterException(e)) {
                    itemAdapter.setMessageList(messageList);
                    recyclerView.setAdapter(itemAdapter);
                    itemAdapter.setDeliveredAndReadMark(imConversation.getLastDeliveredAt(),
                            imConversation.getLastReadAt());
                    itemAdapter.notifyDataSetChanged();
                    scrollToBottom();
                    clearUnreadConut();
                }
            }
        });
    }

    /**
     * 输入事件处理，接收后构造成 AVIMTextMessage 然后发送
     * 因为不排除某些特殊情况会受到其他页面过来的无效消息，所以此处加了 tag 判断
     */
    @Subscribe
    public void onEvent(InputBottomBarTextEvent textEvent) {
        if (null != imConversation && null != textEvent) {
            if (!TextUtils.isEmpty(textEvent.sendContent) && imConversation.getConversationId().equals(textEvent.tag)) {
                sendText(textEvent.sendContent);
            }
        }
    }

    /**
     * 处理推送过来的消息
     * 同理，避免无效消息，此处加了 conversation id 判断
     */
    @Subscribe
    public void onEvent(TypeMessageEvent messageEvent) {
        //TODO 判断类型
        if (null != imConversation && null != messageEvent &&
                imConversation.getConversationId().equals(messageEvent.conversation.getConversationId())) {
            itemAdapter.addMessage(messageEvent.message);
            itemAdapter.notifyDataSetChanged();
            scrollToBottom();
            clearUnreadConut();
        }
    }

    /**
     * 重新发送已经发送失败的消息
     */
    @Subscribe
    public void onEvent(MessageResendEvent resendEvent) {
        if (null != imConversation && null != resendEvent &&
                null != resendEvent.message && imConversation.getConversationId().equals(resendEvent.message.getConversationId())) {
            if (AVIMMessage.AVIMMessageStatus.AVIMMessageStatusFailed == resendEvent.message.getMessageStatus()
                    && imConversation.getConversationId().equals(resendEvent.message.getConversationId())) {
                sendMessage(resendEvent.message, false);
            }
        }
    }

    /**
     * 更新对方已读的位置事件
     *
     * @param readEvent
     */
    @Subscribe
    public void onEvent(ConversationReadStatusEvent readEvent) {
        if (null != imConversation && null != readEvent &&
                imConversation.getConversationId().equals(readEvent.conversationId)) {
            itemAdapter.setDeliveredAndReadMark(imConversation.getLastDeliveredAt(),
                    imConversation.getLastReadAt());
            itemAdapter.notifyDataSetChanged();
        }
    }

    @Subscribe
    public void onEvent(final MessageUpdateEvent event) {
        if (null != imConversation && null != event &&
                null != event.message && imConversation.getConversationId().equals(event.message.getConversationId())) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle("操作").setItems(new String[]{"撤回", "修改消息内容"}, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (0 == which) {
                        recallMessage(event.message);
                    } else if (1 == which) {
                        showUpdateMessageDialog(event.message);
                    }
                }
            });
            builder.create().show();
        }
    }

    @Subscribe
    public void onEvent(final MessageUpdatedEvent event) {
        if (null != imConversation && null != event &&
                null != event.message && imConversation.getConversationId().equals(event.message.getConversationId())) {
            itemAdapter.updateMessage(event.message);
        }
    }

    private void showUpdateMessageDialog(final AVIMMessage message) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        final EditText editText = new EditText(getActivity());
        builder.setView(editText);
        builder.setTitle("修改消息内容");
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.setPositiveButton("提交", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                String content = editText.getText().toString();
                updateMessage(message, content);
            }
        });
        builder.show();
    }

    private void recallMessage(AVIMMessage message) {
        imConversation.recallMessage(message, new AVIMMessageRecalledCallback() {
            @Override
            public void done(AVIMRecalledMessage recalledMessage, AVException e) {
                if (null == e) {
                    itemAdapter.updateMessage(recalledMessage);
                } else {
                    Toast.makeText(getActivity(), "撤回失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void updateMessage(AVIMMessage message, String newContent) {
        AVIMTextMessage textMessage = new AVIMTextMessage();
        textMessage.setText(newContent);
        imConversation.updateMessage(message, textMessage, new AVIMMessageUpdatedCallback() {
            @Override
            public void done(AVIMMessage message, AVException e) {
                if (null == e) {
                    itemAdapter.updateMessage(message);
                } else {
                    Toast.makeText(getActivity(), "更新失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    /**
     * 处理录音事件
     *
     * @param recordEvent
     */
    @Subscribe
    public void onEvent(InputBottomBarRecordEvent recordEvent) {
        if (null != imConversation && null != recordEvent &&
                !TextUtils.isEmpty(recordEvent.audioPath) &&
                imConversation.getConversationId().equals(recordEvent.tag)) {
            if (recordEvent.audioDuration > 0)
                Log.i("tag", recordEvent.audioDuration + "---------------------------");
            sendAudio(recordEvent.audioPath);
        }
    }

    /**
     * 发送语音消息
     *
     * @param audioPath
     */
    protected void sendAudio(String audioPath) {
        try {
            LogUtils.i(audioPath);
            String name = ChatKit.getInstance().getcurrentUserName() + "-" + System.currentTimeMillis() + ".mp3";
            AVFile file = AVFile.withAbsoluteLocalPath(name, audioPath);
            AVIMAudioMessage audioMessage = new AVIMAudioMessage(file);
            sendMessage(audioMessage);
        } catch (IOException e) {
            LogUtils.logException(e);
        }
    }

    /**
     * 处理输入栏发送过来的事件
     *
     * @param event
     */
    @Subscribe
    public void onEvent(InputBottomBarEvent event) {
        if (null != imConversation && null != event && imConversation.getConversationId().equals(event.tag)) {
            switch (event.eventAction) {
                case InputBottomBarEvent.INPUTBOTTOMBAR_IMAGE_ACTION:
                    dispatchPickPictureIntent();
                    break;
                case InputBottomBarEvent.INPUTBOTTOMBAR_CAMERA_ACTION:
//                    dispatchTakePictureIntent();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 发送 Intent 跳转到系统图库页面
     */
    private void dispatchPickPictureIntent() {
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, null);
        photoPickerIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(photoPickerIntent, REQUEST_IMAGE_PICK);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (Activity.RESULT_OK == resultCode) {
            switch (requestCode) {

                case REQUEST_IMAGE_PICK:
                    sendImage(getRealPathFromURI(getActivity(), data.getData()));
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 滚动 recyclerView 到底部
     */
    private void scrollToBottom() {
        layoutManager.scrollToPositionWithOffset(itemAdapter.getItemCount() - 1, 0);
    }

    /**
     * 根据 Uri 获取文件所在的位置
     *
     * @param context
     * @param contentUri
     * @return
     */
    private String getRealPathFromURI(Context context, Uri contentUri) {
        if (contentUri.getScheme().equals("file")) {
            return contentUri.getEncodedPath();
        } else {
            Cursor cursor = null;
            try {
                String[] proj = {MediaStore.Images.Media.DATA};
                cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
                if (null != cursor) {
                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                    cursor.moveToFirst();
                    return cursor.getString(column_index);
                } else {
                    return "";
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
    }

    /**
     * 发送图片消息
     *
     * @param imagePath
     */
    protected void sendImage(String imagePath) {
        try {
            sendMessage(new AVIMImageMessage(imagePath));
        } catch (IOException e) {
            LogUtils.logException(e);
        }
    }

    /**
     * 发送文本消息
     *
     * @param content
     */
    protected void sendText(String content) {
        AVIMTextMessage message = new AVIMTextMessage();
        message.setText(content);
        sendMessage(message);
    }


    public void sendMessage(AVIMMessage message) {
        sendMessage(message, true);
    }

    /**
     * 发送消息
     *
     * @param message
     */
    public void sendMessage(final AVIMMessage message, boolean addToList) {
        if (addToList) {
            itemAdapter.addMessage(message);
        }
        itemAdapter.notifyDataSetChanged();
        scrollToBottom();
        AVIMMessageOption option = new AVIMMessageOption();
        option.setReceipt(true);
        imConversation.sendMessage(message, option, new AVIMConversationCallback() {
            @Override
            public void done(AVIMException e) {
                itemAdapter.notifyDataSetChanged();
                if (null != e) {
                    LogUtils.logException(e);
                }
            }
        });

    }

    private boolean filterException(Exception e) {
        if (null != e) {
            LogUtils.logException(e);
            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
        }
        return (null == e);
    }

    private void clearUnreadConut() {
        if (imConversation.getUnreadMessagesCount() > 0) {
            imConversation.read();
        }
    }
}
